#pragma once
#include "TcpServer.hpp"
#include "Util.hpp"
#include <memory>
#include <sstream>
#include <unordered_map>

//应答报头的分隔符
const std::string gspace = " ";
const std::string newline = "\r\n";
const std::string gesp = ": ";

const std::string webroot = "./webroot";
const std::string firstpage = "/index.html";

// 接受请求的处理
class HttpRequest
{
public:
    HttpRequest()
    {
    }
    // 序列化(不用实现,因为不会享客户端发送请求)
    std::string Serialize()
    {
        return nullptr;
    }
    // 反序列化
    bool DeSerialize(std::string &reqhead,std::string &reqtext)
    {
        std::string line;
        //提取第一行
        Util::ReadOneLine(reqhead, line, newline);
        std::stringstream ss(line);
        ss >> req_method >> _uri >> _version;
        // std::cout << "req_method" << req_method << std::endl;
        // std::cout << "_uri" << _uri << std::endl;
        // std::cout << "_version" << _version << std::endl;
        return true;
    }
    std::string Uri(){return _uri;}
    ~HttpRequest()
    {
    }

private:
    std::string req_method; // 请求方法
    std::string _uri;       // uri(文件路径)
    std::string _version;   // HTTP版本

    std::unordered_map<std::string, std::string> _headers; // 请求报头
    std::string _blackline;                                // 空行
    std::string _text;                                     // 正文
};

// 应答处理
class HttpResponse
{
public:
    HttpResponse():_blankline(newline)
    {
    }
    // 序列化(实现)
    std::string Serialize()
    {
        std::string result;
        //状态行信息
        result = _version + gspace + std::to_string(_code) + gspace + _desc + newline;
        //响应报头
        for(auto& head:_headers)
        {
            result += head.first + gesp +head.second + gspace;
        }
        //空行
        result += _blankline;
        //正文
        result += _text;
        return result;
    }
    // 反序列化
    bool ReSerialize()
    {
    }
    ~HttpResponse()
    {
    }

public:
    std::string _version; // HTTP版本
    int _code;            // 状态码
    std::string _desc;    // 状态码描述

    std::unordered_map<std::string, std::string> _headers; // 响应报头
    std::string _blankline;                                 // 空行
    std::string _text;                                     // 正文
};
// http协议
class Http
{
public:
    // 构造函数(HTTP底层基于tcp)
    Http(uint16_t port) : tsvrp(std::make_unique<TcpServer>(port))
    {
    }
    //判断是否读到了完整的报头
    bool Decode(std::string& message, std::string& head, std::string& text)
    {
        auto pos = message.find(newline + newline);
        if(pos == std::string::npos)
        {
            //未读取到一个完成的报头
            return false;
        }
        //一定读取到至少一个完整的报头
        //找到正文的长度
        std::string tmp = "Content-Length" + gesp;
        auto pos1 = message.find(tmp);//定位到Content-Length行
        head = message.substr(0, pos);
        if(pos1 == std::string::npos)
        {
            //没有正文
            return true;
        }
        auto pos2 = message.find(newline, pos1);//从pos1开始找换行符
        pos1 = pos1 + tmp.size();
        int text_len = std::stoi(message.substr(pos1, pos2));
        //报头字符串

        int sum_len = head.size() + text_len + 2 * newline.size();
        if(message.size() < sum_len)
        {
            return false;
        }
        //一定有一套完整的请求

        text = message.substr(pos + 2 * newline.size(), sum_len);
        message.erase(0,sum_len);
        return true;
    }
    // http协议的接收和返回
    void HandlHttpResquest(std::shared_ptr<Socket> &sock, Inet_Addr addr)
    {
        std::string message; // 获取读到的字符串
        int n = sock->Recv(&message);//无法确定读到的是否为一个完整的请求,可以通过空行来读取完整的报头,再根据报头中的Length提取内容
        if(n > 0)
        {
            //读取成功
            std::string head;
            std::string text("NULL");

            if(Decode(message,head,text))
            {
                // std::cout << head << std::endl;
                // std::cout << "-------------------------------------------------------" << std::endl;
                // std::cout << text << std::endl;
                std::cout << message << std::endl;
                HttpRequest req;
                req.DeSerialize(head, text);
                std::string uri = req.Uri();
                std::string path;
                if(uri == "/")
                {
                    path = webroot + firstpage;
                }
                else
                {
                    path = webroot + uri;
                }
                HttpResponse res;
                res._version = "HTTP/1.1";
                res._code = 200;
                res._desc = "OK";
                Util::tools(path, res._text);
                std::string result = res.Serialize();
                sock->Send(result);

            }
        }

// #ifndef DEBUG
// #define DEBUG
//         // 读取请求
//         std::string message; // 获取读到的字符串
//         sock->Recv(&message);//无法确定读到的是否为一个完整的请求,可以通过空行来读取完整的报头,再根据报头中的Length提取内容
//         std::cout << message;//输出读到的字符串
//         HttpResponse req;
//         req._version = "HTTP/1.1";
//         req._code = 200;
//         req._desc = "OK";
//         //文件路径初始化
//         std::string path = webroot + firstpage;
//         bool r = Util::tools(path, req._text);
//         (void) r;
//         std::string result = req.Serialize();
//         sock->Send(result);
// #endif
    }
    // 服务器的入口
    void Start()
    {
        // 将Http协议的方法绑定给TcpServer,
        // 使得与客户端建立好链接后直接进入Http服务模块进行对应的请求处理
        tsvrp->Start([this](std::shared_ptr<Socket> &sock, Inet_Addr addr)
                     { this->HandlHttpResquest(sock, addr); });
    }
    ~Http()
    {
    }

private:
    std::unique_ptr<TcpServer> tsvrp;
};